home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume8 / se / part03 < prev    next >
Encoding:
Internet Message Format  |  1987-01-25  |  47.6 KB

  1. Subject:  v08i003:  Georgia Tech 'se' Screen Editor
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: emoryu1!arnold (Arnold D. Robbins)
  6. Mod.sources: Volume 8, Issue 3
  7. Archive-name: se/Part03
  8.  
  9.  
  10. Here is the second release of the Georgia Tech Screen Editor, 'se'.
  11. There were enough changes that a whole new posting is warranted.
  12.  
  13. Major Changes:
  14.     All Georgia Tech specific stuff removed.
  15.     It understands window size changes on 4.3BSD and ATT Unix PC/3B1
  16.     Support for the shared library on the ATT Unix PC/3B1
  17.     Considerable source code reorganization in certain files.
  18.  
  19. Enjoy,
  20.  
  21. Arnold Robbins
  22.  
  23. #! /bin/sh
  24. # This is a shell archive, meaning:
  25. # 1. Remove everything above the #! /bin/sh line.
  26. # 2. Save the resulting text in a file.
  27. # 3. Execute the file with /bin/sh (not csh) to create the files:
  28. #    scratch.c
  29. #    screen.c
  30. #    scriptse.1
  31. #    scriptse.c
  32. #    se.h
  33. #    where
  34. export PATH; PATH=/bin:$PATH
  35. echo shar: extracting "'scratch.c'" '(11621 characters)'
  36. if test -f 'scratch.c'
  37. then
  38.     echo shar: will not over-write existing file "'scratch.c'"
  39. else
  40. cat << \SHAR_EOF > 'scratch.c'
  41. #ifndef lint
  42. static char RCSid[] = "$Header: scratch.c,v 1.2 86/07/17 17:21:38 arnold Exp $";
  43. #endif
  44.  
  45. /*
  46.  * $Log:    scratch.c,v $
  47.  * Revision 1.2  86/07/17  17:21:38  arnold
  48.  * Calls to error() changed to reflect whether or not to coredump.
  49.  * 
  50.  * Revision 1.1  86/05/06  13:38:04  osadr
  51.  * Initial revision
  52.  * 
  53.  * 
  54.  */
  55.  
  56. /*
  57. ** scratch.c
  58. **
  59. ** scratch file handling for se screen editor.
  60. **
  61. ** If OLD_SCRATCH is defined, then this file will contain the
  62. ** original scratch file handling, based on linked lists,
  63. ** from the ratfor version of Software Tools.  This method is
  64. ** real good at moving lines around, but is poor for finding lines.
  65. **
  66. ** If OLD_SCRATCH is not defined, which is the default, this file will use
  67. ** the line handling methodology presented in Software Tools In Pascal,
  68. ** *without* changing the way any of the routines are called.
  69. **
  70. ** Bascially, the lines are always kept in order in the Buf array.
  71. ** Thus, lines 1 through 5 are in Buf[1] through Buf[5]. blkmove() and
  72. ** reverse() do the work of moving lines around in the buffer. The alloc()
  73. ** routine, therefore, always allocates the first empty slot, which will be
  74. ** at Lastln + 1, if there is room.
  75. **
  76. ** Deleted lines are kept at the end of the buffer. Limbo points to the first
  77. ** line in the group of lines which were last deleted, or else Limbo == NOMORE.
  78. **
  79. ** It is a very good idea to read the chapters on editing in BOTH editions of
  80. ** Software Tools, before trying to muck with this. It also helps to be a
  81. ** little bit off the wall....
  82. **
  83. ** In fact, I would go as far as saying, "If you touch this, it will break.
  84. ** It is held together with chewing gum, scotch tape, and bobby pins."
  85. ** (Of course, you could always use OLD_SCRATCH, which definitely works.
  86. ** It just increases the size of the editor.)  So much for the old
  87. ** "Just replace the implementation of the underlying primitives..."
  88. */
  89.  
  90. #include "se.h"
  91. #include "extern.h"
  92.  
  93. /* alloc --- allocate space for a new pointer block */
  94.  
  95.  
  96. static LINEDESC *alloc (ptr)
  97. register LINEDESC **ptr;
  98. {
  99. #ifdef OLD_SCRATCH    /* old way */
  100.     if (Free == NOMORE)   /* no free list, expand into unallocated space */
  101.     {
  102.         if (Lastbf - Buf + BUFENT <= MAXBUF)   /* see if there's room */
  103.         {
  104.             *ptr = Lastbf;
  105.             Lastbf += BUFENT;
  106.         }
  107.         else
  108.             *ptr = NOMORE;        /* out of pointer space */
  109.     }
  110.     else    /* remove a block from free list */
  111.     {
  112.         *ptr = Free;
  113.         Free = Free->Prevline;
  114.     }
  115. #else    /* new way */
  116.     int limbo_index = Limbo - Buf;    /* use indices instead of pointers */
  117.         /* N.B.: this statement is meaningless if Limbo == NOMORE */
  118.         /* but if so, we don't use limbo_index anyway */
  119.  
  120.     if (Limbo == NOMORE)
  121.         if (Lastln < (MAXBUF - 1) - 1)    /* dumb zero based indexing! */
  122.             *ptr = &Buf[Lastln + 1];
  123.         else
  124.             *ptr = NOMORE;
  125.     else if (limbo_index - Lastln > 1)
  126.         *ptr = &Buf[Lastln + 1];
  127.     else
  128.         *ptr = NOMORE;
  129. #endif
  130.  
  131.     return (*ptr);
  132. }
  133.  
  134.  
  135. /* bump --- advance line number and corresponding index simultaneously */
  136.  
  137. bump (line, ix, way)
  138. int *line, way;
  139. LINEDESC **ix;
  140. {
  141.     if (way == FORWARD)    /* increment line number */
  142.     {
  143. #ifdef OLD_SCRATCH
  144.         *ix = (*ix)->Nextline;
  145.         if (*ix == Line0)
  146.             *line = 0;
  147.         else
  148.             (*line)++;
  149. #else
  150.         (*ix)++;
  151.         if (*ix == &Buf[Lastln+1])
  152.         {
  153.             *line = 0;
  154.             *ix = Line0;
  155.         }
  156.         else
  157.             (*line)++;
  158. #endif
  159.     }
  160.     else    /* decrement line number */
  161.     {
  162.         if (*ix == Line0)
  163.             *line = Lastln;
  164.         else
  165.             (*line)--;
  166. #ifdef OLD_SCRATCH
  167.         *ix = (*ix)->Prevline;
  168. #else
  169.         if (*ix == Line0)
  170.             *ix = &Buf[Lastln];
  171.         else
  172.             (*ix)--;
  173. #endif
  174.     }
  175. }
  176.  
  177.  
  178.  
  179. /* closef --- close a file */
  180.  
  181. static closef (fd)
  182. filedes fd;
  183. {
  184.     close (fd);
  185. }
  186.  
  187.  
  188.  
  189.  
  190. /* clrbuf --- purge scratch file */
  191.  
  192. clrbuf ()
  193. {
  194.  
  195.     if (Lastln > 0)
  196.         svdel (1, Lastln);
  197.  
  198.     closef (Scr);
  199.     unlink (Scrname);
  200. }
  201.  
  202.  
  203.  
  204. /* garbage_collect --- compress scratch file */
  205.  
  206. garbage_collect ()
  207. {
  208.     char new_name [MAXLINE];
  209.     register int i, new_scrend;
  210.     int new_fd;
  211.     register LINEDESC *p;
  212.  
  213.     makscr (&new_fd, new_name);
  214.     remark ("collecting garbage");
  215.     new_scrend = 0;
  216. #ifdef OLD_SCRATCH
  217.     for (p = Limbo, i = 1; i <= Limcnt; p = p->Nextline, i++)
  218. #else
  219.     for (p = Limbo, i = 1; i <= Limcnt; p++, i++)
  220. #endif
  221.     {
  222.         gtxt (p);
  223.         seekf ((long) new_scrend * 8, new_fd);
  224.         writef (Txt, (int) p->Lineleng, new_fd);
  225.         p->Seekaddr = new_scrend;
  226.         new_scrend += (p->Lineleng + 7) / 8;
  227.     }
  228. #ifdef OLD_SCRATCH
  229.     for (p = Line0, i = 0; i <= Lastln; p = p->Nextline, i++)
  230. #else
  231.     for (p = Line0, i = 0; i <= Lastln; p++, i++)
  232. #endif
  233.     {
  234.         gtxt (p);
  235.         seekf ((long) new_scrend * 8, new_fd);
  236.         writef (Txt, (int) p->Lineleng, new_fd);
  237.         p->Seekaddr = new_scrend;
  238.         new_scrend += (p->Lineleng + 7) / 8;
  239.     }
  240.  
  241.     closef (Scr);
  242.     unlink (Scrname);
  243.  
  244.     Scr = new_fd;
  245.     sprintf (Scrname, "%s", new_name);
  246.     Scrend = new_scrend;
  247.     Lost_lines = 0;
  248.  
  249.     remark ("");
  250. }
  251.  
  252.  
  253.  
  254. /* gettxt --- locate text for line, copy to txt */
  255.  
  256. LINEDESC *gettxt (line)
  257. int line;
  258. {
  259.     register LINEDESC *k;
  260.     LINEDESC *getind ();
  261.  
  262.     k = getind (line);
  263.     gtxt (k);
  264.  
  265.     return (k);
  266. }
  267.  
  268.  
  269.  
  270. /* gtxt --- retrieve a line from the scratch file */
  271.  
  272. gtxt (ptr)
  273. register LINEDESC *ptr;
  274. {
  275.     int readf ();
  276.  
  277.     seekf ((long) ptr->Seekaddr * 8, Scr); /* position to start of file */
  278.     /*
  279.      * rounded Seekaddr to 8 byte sections, giving larger
  280.      * buffer space for text (*8)
  281.      */
  282.  
  283.     return (readf (Txt, (int) ptr->Lineleng, Scr) - 1);
  284. }
  285.  
  286.  
  287.  
  288. /* inject --- insert a new line after curln */
  289.  
  290. inject (lin)
  291. register char lin [];
  292. {
  293.     register int i;
  294.     int maklin ();
  295.     register LINEDESC *k1, *k2;
  296.     LINEDESC *k3;
  297.     LINEDESC *getind ();
  298.  
  299.     for (i = 0; lin [i] != EOS; )
  300.     {
  301.         i = maklin (lin, i, &k3);       /* create a single line */
  302.         if (i == ERR)
  303.         {
  304.             Errcode = ECANTINJECT;
  305.             return (ERR);
  306.         }
  307. #ifdef OLD_SCRATCH
  308.         k1 = getind (Curln);            /* get pointer to curln */
  309.         k2 = k1-> Nextline;             /* get pointer to nextln */
  310.         relink (k1, k3, k3, k2);        /* set pointers of new line */
  311.         relink (k3, k2, k1, k3);        /* set pointers of prev, next */
  312.         svins (Curln, 1);
  313.         Lastln++;        /* update Lastln */
  314. #else
  315.         Lastln++;        /* update Lastln */
  316.         blkmove (Lastln, Lastln, Curln);
  317.         svins (Curln, 1);
  318. #endif
  319.         Curln++;        /* update Curln */
  320.     }
  321.     return (OK);
  322. }
  323.  
  324.  
  325.  
  326. /* maklin --- construct a new line, add to scratch file */
  327.  
  328. maklin (lin, i, newind)
  329. register char lin [];
  330. register int i;
  331. LINEDESC **newind;
  332. {
  333.  
  334.     char text [MAXLINE];
  335.     register int l, n;
  336.     LINEDESC *ptr;
  337.     LINEDESC *alloc ();
  338.  
  339.     if (alloc (&ptr) == NOMORE)     /* get space for pointer block */
  340.         return (ERR);
  341.  
  342.     for (n = i; lin [n] != EOS; n++)    /* find end of line */
  343.         if (lin [n] == '\n')
  344.         {
  345.             n++;
  346.             break;
  347.         }
  348.  
  349.     if (n - i >= MAXLINE )  /* can't handle more than MAXLINE chars/line */
  350.         n = i + MAXLINE - 1;
  351.     l = n - i + 1;          /* length of new line (including EOS) */
  352.  
  353.     move_ (&lin [i], text, l);      /* move new line into text */
  354.     text [l - 1] = EOS;             /* add EOS */
  355.  
  356.     ptr->Seekaddr = Scrend; /* will be added to end of scratch file */
  357.     ptr->Lineleng = l;      /* line length including EOS */
  358.     ptr->Globmark = NO;     /* not marked for Global command */
  359.     ptr->Markname = DEFAULTNAME;    /* give it default mark name */
  360.  
  361.     seekf ((long) Scrend * 8, Scr); /* go to end of scratch file */
  362.     writef (text, l, Scr);          /* write line on scratch file */
  363.     Scrend += (l + 7) / 8;          /* update end-of-file pointer */
  364.  
  365.     Buffer_changed = YES;
  366.  
  367.     *newind = ptr;                  /* return index of new line */
  368.     return (n);                     /* return next char of interest in lin */
  369. }
  370.  
  371.  
  372.  
  373. /* makscr --- create a new scratch file */
  374.  
  375. makscr (fd, str)
  376. register filedes *fd;
  377. register char str[];
  378. {
  379.     register int i;
  380.  
  381.     for (i = 0; i <= 9; i++)
  382.     {
  383.         sprintf (str, "/usr/tmp/se%d.%d", getpid(), i);
  384.         /* create str name in /usr/tmp */
  385.         if ((*fd = open (str, 0)) < 0)
  386.         {
  387.             /* if the file is not there, close it and create it */
  388.             close (*fd);
  389.             if ((*fd = creat (str, 0700)) > 0)
  390.             {
  391.                 close (*fd);
  392.                 if ((*fd = open (str, 2)) > 0)
  393.                     return;
  394.             }
  395.         }
  396.         else
  397.             close (*fd);
  398.  
  399.     }
  400.     error (YES, "can't create scratch file");
  401. }
  402.  
  403.  
  404.  
  405. /* nextln --- get line after "line" */
  406.  
  407. nextln (line)
  408. int line;
  409. {
  410.     register int ret;
  411.  
  412.     ret = line + 1;
  413.     if (ret > Lastln)
  414.         ret = 0;
  415.  
  416.     return (ret);
  417. }
  418.  
  419.  
  420.  
  421. /* prevln --- get line before "line" */
  422.  
  423. prevln (line)
  424. int line;
  425. {
  426.     register int ret;
  427.  
  428.     ret = line - 1;
  429.     if (ret < 0)
  430.         ret = Lastln;
  431.  
  432.     return (ret);
  433. }
  434.  
  435.  
  436.  
  437. /* readf --- read count words from fd into buf */
  438.  
  439. readf (buf, count, fd)
  440. char buf [];
  441. int  count, fd;
  442. {
  443.     register int ret;
  444.  
  445.     ret = read (fd, buf, count);
  446.     if (ret != count)
  447.         error (YES, "Fatal scratch file read error");
  448.  
  449.     return (ret);
  450. }
  451.  
  452.  
  453. #ifdef OLD_SCRATCH
  454. /* relink --- rewrite two half links */
  455.  
  456. relink (a, x, y, b)
  457. LINEDESC *a, *b, *x, *y;
  458. {
  459.     x->Prevline = a;
  460.     y->Nextline = b;
  461. }
  462. #endif
  463.  
  464.  
  465.  
  466. /* seekf --- position file open on fd to pos */
  467.  
  468. static seekf (pos, fd)
  469. long pos;
  470. filedes fd;
  471. {
  472.     register long ret;
  473.     long lseek ();
  474.  
  475.     ret = lseek (fd, pos, 0);               /* abs seek */
  476.     if (ret != pos)
  477.         error (YES, "Fatal scratch file seek error");
  478.     return (OK);
  479. }
  480.  
  481.  
  482.  
  483. /* mkbuf --- create scratch file, initialize line 0 */
  484.  
  485. mkbuf ()
  486. {
  487.     LINEDESC *p;
  488.  
  489.     makscr (&Scr, Scrname);    /* create a scratch file */
  490.     Scrend = 0;        /* initially empty */
  491.  
  492.     Curln = 0;
  493. #ifdef OLD_SCRATCH
  494.     Lastln = 0;
  495. #else
  496.     Lastln = -1;        /* alloc depends on this... */
  497. #endif
  498.  
  499. #ifdef OLD_SCRATCH
  500.     Lastbf = &Buf[0];       /* next word available for allocation ?? */
  501.     Free = NOMORE;          /* free list initially empty */
  502. #endif
  503.     Limbo = NOMORE;         /* no lines in limbo */
  504.     Limcnt = 0;
  505.     Lost_lines = 0;         /* no garbage in scratch file yet */
  506.  
  507.     maklin ("", 0, &p);     /* create an empty line */
  508. #ifdef OLD_SCRATCH
  509.     relink (p, p, p, p);    /* establish initial linked list */
  510. #endif
  511.     p->Markname = EOS;    /* give it an illegal mark name */
  512.     Line0 = p;              /* henceforth and forevermore */
  513.  
  514. #ifndef OLD_SCRATCH
  515.     Lastln = 0;
  516. #endif
  517. }
  518.  
  519.  
  520.  
  521. /* sp_inject --- special inject for reading files */
  522.  
  523. LINEDESC *sp_inject (lin, len, line)
  524. char lin[];
  525. int  len;
  526. LINEDESC *line;
  527. {
  528.     register LINEDESC *k, *ret;
  529.     LINEDESC *ptr;
  530.     LINEDESC *alloc ();
  531.  
  532.     ret = alloc (&ptr);
  533.     if (ptr == NOMORE)
  534.     {
  535.         Errcode = ECANTINJECT;
  536.         return (ret);
  537.     }
  538.  
  539.     ptr->Seekaddr = Scrend;
  540.     ptr->Lineleng = len + 1;
  541.     ptr->Globmark = NO;
  542.     ptr->Markname = DEFAULTNAME;
  543.  
  544.     seekf ((long) Scrend * 8, Scr);
  545.     writef (lin, len + 1, Scr);
  546.     Scrend += ((len + 1) + 7) / 8;          /* fudge for larger buffer */
  547.     Lastln++;
  548.  
  549.     Buffer_changed = YES;
  550.  
  551. #ifdef OLD_SCRATCH
  552.     k = line->Nextline;
  553.     relink (line, ptr, ptr, k);
  554.     relink (ptr, k, line, ptr);
  555. #else
  556.     /*
  557.      * this part dependant on the fact that we set
  558.      * Curln = line in the routine do_read.
  559.      */
  560.     blkmove (ptr - Buf, ptr - Buf, Curln);    /* need line no's */
  561.     Curln++;
  562. #endif
  563.  
  564.     return (ret);
  565. }
  566.  
  567.  
  568.  
  569. /* writef --- write count words from buf onto fd */
  570.  
  571. writef (buf, count, fd)
  572. char buf[];
  573. int  count;
  574. filedes fd;
  575. {
  576.     register int ret;
  577.  
  578.     ret = write (fd, buf, count);
  579.     if (ret != count)
  580.         error (YES, "Fatal scratch file write error");
  581.     return (ret);
  582. }
  583.  
  584.  
  585.  
  586. /* getind --- locate line index in buffer */
  587.  
  588. LINEDESC *getind (line)
  589. register int line;
  590. {
  591. #ifdef OLD_SCRATCH
  592.     register LINEDESC *k;
  593.  
  594.     k = Line0;
  595.     line++;
  596.     while (--line)
  597.         k = k->Nextline;
  598.  
  599.     return (k);
  600. #else
  601.     return (&Buf[line]);
  602. #endif
  603. }
  604.  
  605. #ifndef OLD_SCRATCH
  606.  
  607. /* blkmove -- use SWT in Pascal line handling */
  608.  
  609. blkmove (n1, n2, n3)    /* move block of lines n1..n2 to after n3 */
  610. int n1, n2, n3;
  611. {
  612.     if (n3 < n1 -1)
  613.     {
  614.         reverse (n3 + 1, n1 - 1);
  615.         reverse (n1, n2);
  616.         reverse (n3 + 1, n2);
  617.     }
  618.     else if (n3 > n2)
  619.     {
  620.         reverse (n1, n2);
  621.         reverse (n2 + 1, n3);
  622.         reverse (n1, n3);
  623.     }
  624. }
  625.  
  626. /* reverse -- reverse buf[n1]..buf[n2] */
  627.  
  628. reverse (n1, n2)
  629. register int n1, n2;
  630. {
  631.     LINEDESC temp;
  632.  
  633.     while (n1 < n2)
  634.     {
  635.         temp = Buf[n1];
  636.         Buf[n1] = Buf[n2];
  637.         Buf[n2] = temp;
  638.         n1++;
  639.         n2--;
  640.     }
  641. }
  642. #endif
  643. SHAR_EOF
  644. fi # end of overwriting check
  645. echo shar: extracting "'screen.c'" '(23199 characters)'
  646. if test -f 'screen.c'
  647. then
  648.     echo shar: will not over-write existing file "'screen.c'"
  649. else
  650. cat << \SHAR_EOF > 'screen.c'
  651. #ifndef lint
  652. static char RCSid[] = "$Header: screen.c,v 1.3 86/07/17 17:22:19 arnold Exp $";
  653. #endif
  654.  
  655. /*
  656.  * $Log:    screen.c,v $
  657.  * Revision 1.3  86/07/17  17:22:19  arnold
  658.  * Senddelay() moved to term.c, where it belongs.
  659.  * 
  660.  * Revision 1.2  86/05/27  17:46:46  osadr
  661.  * Fix for early 4.2 BSD systems to use <sys/time.h> instead of <time.h>.
  662.  * 
  663.  * Revision 1.1  86/05/06  13:38:18  osadr
  664.  * Initial revision
  665.  * 
  666.  * 
  667.  */
  668.  
  669. /*
  670. ** screen.c
  671. **
  672. ** screen handling functions for the screen editor.
  673. */
  674.  
  675.  
  676. #include "se.h"
  677. #include "extern.h"
  678. #ifdef BSD4_2
  679. #include <sys/time.h>
  680. #else
  681. #include <time.h>
  682. #endif
  683.  
  684. /* clrrow --- clear out all of a row except the bar */
  685.  
  686. clrrow (row)
  687. register int row;
  688. {
  689.     loadstr ("", row, 0, BARCOL - 1);
  690.     loadstr ("", row, BARCOL + 1, Ncols - 1);
  691. }
  692.  
  693.  
  694.  
  695. /* display_message --- copy contents of message file to screen */
  696.  
  697. display_message (fp)
  698. FILE *fp;
  699. {
  700.     char lin[MAXCOLS];
  701.     char *fgets ();
  702.     int row, col, eof, k;
  703.     static char more[] = " M O R E   T O   C O M E ";
  704.  
  705.     if (Toprow > 0)
  706.     {
  707.         Topln = max (0, Topln - (Toprow - 1));
  708.         Toprow = 0;
  709.     }
  710.  
  711.     eof = NO;
  712.     for (row = Toprow; row <= Botrow; row++)
  713.     {
  714.         if (fgets (lin, Ncols, fp) == NULL)
  715.         {
  716.             eof = YES;
  717.             break;
  718.         }
  719.         Toprow++;
  720.         Topln++;
  721.         lin[strlen (lin)] = EOS;        /* remove '\n' */
  722.         loadstr (lin, row, 0, Ncols);
  723.     }
  724.  
  725.     if (eof == NO)
  726.     {
  727.         k = (Ncols - strlen (more)) / 2;
  728.         for (col = 0; col < k; col++)
  729.             load ('*', row, col);
  730.  
  731.         for (k = 0; more[k] != EOS; k++, col++)
  732.             load (more[k], row, col);
  733.  
  734.         for (; col < Ncols; col++)
  735.             load ('*', row, col);
  736.  
  737.         Toprow++;
  738.         Topln++;
  739.         row++;
  740.     }
  741.  
  742.     for (col = 0; col < Ncols; col++)
  743.         load ('-', row, col);
  744.     Toprow++;
  745.     Topln++;
  746.  
  747.     if (Topln > Lastln)
  748.         adjust_window (0, Lastln);
  749.  
  750.     if (Curln < Topln)
  751.         Curln = Topln;
  752.  
  753.     First_affected = Topln;        /* must rewrite the whole screen */
  754.  
  755.     mesg ("Enter o- to restore display", HELP_MSG);
  756.  
  757.     if (eof == YES)
  758.         return (EOF);
  759.  
  760.     return (OK);
  761. }
  762.  
  763. static char smargin[] = "MARGIN";
  764.  
  765. /* getcmd --- read a line from the terminal (for se) */
  766.  
  767. getcmd (lin, col1, curpos, termchar)
  768. char *lin, *termchar;
  769. int col1, *curpos;
  770. {
  771.     int cursor, nlpos, prev_cursor, prev_status, status,
  772.     scan_pos, tab_pos, first, strlen (),
  773.     scan_tab (), scan_char (), cread ();
  774.     char c;
  775.  
  776.     nlpos = strlen (lin) - 1;
  777.     if (nlpos == -1 || lin[nlpos] != '\n')
  778.         nlpos++;
  779.  
  780.     if (*curpos < 0)
  781.         cursor = 0;
  782.     else if (*curpos >= MAXLINE - 1)
  783.         cursor = nlpos;
  784.     else
  785.         set_cursor (*curpos, &status, &cursor, &nlpos, lin);
  786.     prev_cursor = cursor;
  787.  
  788.     watch ();    /* display the time of day */
  789.  
  790.     switch (Nchoise) {    /* update the line number display */
  791.     case CURLINE:
  792.         litnnum ("line ", Curln, LINE_MSG);
  793.         break;
  794.     case LASTLINE:
  795.         litnnum ("$ = ", Lastln, LINE_MSG);
  796.         break;
  797.     case TOPLINE:
  798.         litnnum ("# = ", Topln, LINE_MSG);
  799.         break;
  800.     default:
  801.         mesg ("", LINE_MSG);
  802.         break;
  803.     }
  804.  
  805.     if (cursor + 1 < Warncol)    /* erase the column display */
  806.         mesg ("", COL_MSG);
  807.  
  808.     *termchar = EOS;    /* not yet terminated */
  809.     status = OK;
  810.     prev_status = ERR;
  811.     first = col1;
  812.  
  813.     while (*termchar == EOS)
  814.     {
  815.         lin[nlpos] = EOS;    /* make sure the line has an EOS */
  816.         if (status == ERR)    /* last iteration generated an error */
  817.             twrite (1, "\007", 1);    /* Bell */
  818.         else if (prev_status == ERR)    /* last one OK but one before had error */
  819.             mesg ("", CHAR_MSG);
  820.  
  821.         prev_status = status;
  822.         status = OK;
  823.  
  824.         if (first > cursor)     /* do horiz. scroll if needed */
  825.             first = cursor;
  826.         else if (first < cursor - Ncols + POOPCOL + 1)
  827.             first = cursor - Ncols + POOPCOL + 1;
  828.  
  829.         if (first == col1)      /* indicate horizontally shifted line */
  830.             load ('|', Cmdrow, BARCOL);
  831.         else if (first > col1)
  832.             load ('<', Cmdrow, BARCOL);
  833.         else if (first < col1)
  834.             load ('>', Cmdrow, BARCOL);
  835.         loadstr (&lin[first], Cmdrow, POOPCOL, Ncols - 1);
  836.  
  837.         if (cursor == Warncol - 1 && prev_cursor < Warncol - 1)
  838.             twrite (1, "\007", 1);   /* Bell */
  839.         if (cursor >= Warncol - 1)
  840.             litnnum ("col ", cursor + 1, COL_MSG);
  841.         else if (prev_cursor >= Warncol - 1)
  842.             mesg ("", COL_MSG);
  843.  
  844.         position_cursor (Cmdrow, cursor + POOPCOL - first);
  845.         prev_cursor = cursor;
  846.  
  847.         /* get a character  */
  848.         switch (c = cread()) {        /* branch on character value */
  849.  
  850.     /* Literal characters: */
  851.         case ' ': case '!': case '"': case '#': case '$': case '%': 
  852.         case '&': case '\'': case '(': case ')': case '*': case '+':
  853.         case ',': case '-': case '.': case '/': case '0': case '1': 
  854.         case '2': case '3': case '4': case '5': case '6': case '7':
  855.         case '8': case '9': case ':': case ';': case '<': case '=': 
  856.         case '>': case '?': case '@': case '[': case '\\': case ']':
  857.         case '^': case '_': case '`': case '{': case '|': case '}': 
  858.         case '~': case 'A': case 'B': case 'C': case 'D': case 'E':
  859.         case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': 
  860.         case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q':
  861.         case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': 
  862.         case 'X': case 'Y': case 'Z': case 'a': case 'b': case 'c':
  863.         case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': 
  864.         case 'j': case 'k': case 'l': case 'm': case 'n': case 'o':
  865.         case 'p': case 'q': case 'r': case 's': case 't': case 'u': 
  866.         case 'v': case 'w': case 'x': case 'y': case 'z': case ESC:
  867.             if (c == ESC) /* take next char literally */
  868.             {
  869.                 if ((c = cread()) == '\r')
  870.                     c = '\n';
  871.             }
  872.             else if (Invert_case == YES && isalpha (c))
  873.                 c ^= 040;       /* toggle case (ASCII only) */
  874.             if (Insert_mode == YES)
  875.                 insert (1, &nlpos, &status, cursor, lin);
  876.             else if (cursor >= MAXLINE - 2)
  877.             {
  878.                 status = ERR;
  879.                 mesg (smargin, CHAR_MSG);
  880.             }
  881.             if (status != ERR)
  882.             {
  883.                 lin[cursor++] = c;
  884.                 if (nlpos < cursor)
  885.                     nlpos = cursor;
  886.                 if (c == '\n')
  887.                     *termchar = CURSOR_SAME;
  888.             }
  889.             break;
  890.  
  891.     /* Leftward cursor functions: */
  892.         case CURSOR_LEFT:
  893.             set_cursor (cursor - 1, &status, &cursor, &nlpos, lin);
  894.             break;
  895.  
  896.         case TAB_LEFT:
  897.             tab_pos = scan_tab (TAB_LEFT, cursor, &status);
  898.             if (status != ERR)
  899.                 cursor = tab_pos;
  900.             break;
  901.  
  902.         case SKIP_LEFT:
  903.             cursor = 0;
  904.             break;
  905.  
  906.         case SCAN_LEFT:
  907.             scan_pos = scan_char (c, YES, cursor, nlpos,
  908.                 lin, &status);
  909.             if (status != ERR)
  910.                 cursor = scan_pos;
  911.             break;
  912.  
  913.         case G_LEFT:
  914.             set_cursor (cursor - 1, &status, &cursor, &nlpos, lin);
  915.             if (status != ERR)
  916.                 gobble (1, cursor, &status, &nlpos, lin);
  917.             break;
  918.  
  919.         case G_TAB_LEFT:
  920.             tab_pos = scan_tab (TAB_LEFT, cursor, &status);
  921.             if (status != ERR)
  922.             {
  923.                 cursor = tab_pos;
  924.                 gobble (prev_cursor - tab_pos, cursor,
  925.                     &status, &nlpos, lin);
  926.             }
  927.             break;
  928.  
  929.         case KILL_LEFT:
  930.             cursor = 0;
  931.             gobble (prev_cursor /* - 1 */, cursor, &status, &nlpos, lin);
  932.             break;
  933.  
  934.         case G_SCAN_LEFT:
  935.             scan_pos = scan_char (c, NO, cursor, nlpos,
  936.                 lin, &status);
  937.             if (status != ERR)
  938.             {
  939.                 cursor = scan_pos;
  940.                 gobble (prev_cursor - scan_pos, cursor,
  941.                     &status, &nlpos, lin);
  942.             }
  943.             break;
  944.  
  945.     /* Rightward cursor functions: */
  946.         case CURSOR_RIGHT:
  947.             set_cursor (cursor + 1, &status, &cursor, &nlpos, lin);
  948.             break;
  949.  
  950.         case TAB_RIGHT:
  951.             tab_pos = scan_tab (TAB_RIGHT, cursor, &status);
  952.             if (status != ERR)
  953.                 set_cursor (tab_pos, &status, &cursor,
  954.                     &nlpos, lin);
  955.             break;
  956.  
  957.         case SKIP_RIGHT:
  958.             cursor = nlpos;
  959.             first = col1;
  960.             break;
  961.  
  962.         case SCAN_RIGHT:
  963.             scan_pos = scan_char (c, YES, cursor, nlpos,
  964.                 lin, &status);
  965.             if (status != ERR)
  966.                 cursor = scan_pos;
  967.             break;
  968.  
  969.         case G_RIGHT:
  970.             gobble (1, cursor, &status, &nlpos, lin);
  971.             break;
  972.  
  973.         case G_TAB_RIGHT:
  974.             tab_pos = scan_tab (TAB_RIGHT, cursor,
  975.                 &status);
  976.             if (status != ERR)
  977.                 gobble (tab_pos - cursor, cursor, &status,
  978.                     &nlpos, lin);
  979.             break;
  980.  
  981.         case KILL_RIGHT:
  982.             gobble (nlpos - cursor, cursor, &status, &nlpos, lin);
  983.             break;
  984.  
  985.         case G_SCAN_RIGHT:
  986.             scan_pos = scan_char (c, NO, cursor, nlpos,
  987.                 lin, &status);
  988.             if (status != ERR)
  989.                 gobble (scan_pos - cursor, cursor, &status,
  990.                     &nlpos, lin);
  991.             break;
  992.  
  993.     /* Line termination functions: */
  994.         case T_SKIP_RIGHT:
  995.             cursor = nlpos;
  996.             *termchar = c;
  997.             break;
  998.  
  999.         case T_KILL_RIGHT:
  1000.             nlpos = cursor;
  1001.             *termchar = c;
  1002.             break;
  1003.  
  1004.         case FUNNY:
  1005.         case CURSOR_UP:
  1006.         case CURSOR_DOWN:
  1007.             *termchar = c;
  1008.             break;
  1009.  
  1010.     /* Insertion functions: */
  1011.         case INSERT_BLANK:
  1012.             insert (1, &nlpos, &status, cursor, lin);
  1013.             if (status != ERR)
  1014.                 lin[cursor] = ' ';
  1015.             break;
  1016.  
  1017.         case INSERT_NEWLINE:
  1018.             insert (1, &nlpos, &status, cursor, lin);
  1019.             if (status != ERR)
  1020.             {
  1021.                 lin[cursor] = '\n';
  1022.                 *termchar = CURSOR_UP;
  1023.             }
  1024.             break;
  1025.  
  1026.         case INSERT_TAB:
  1027.             while (lin[cursor] == ' ' || lin[cursor] == '\t')
  1028.                 cursor++;
  1029.             tab_pos = scan_tab (TAB_RIGHT, cursor, &status);
  1030.             if (status != ERR)
  1031.                 insert (tab_pos - cursor, &nlpos, &status,
  1032.                     cursor, lin);
  1033.             if (status != ERR)
  1034.                 for (; cursor < tab_pos; cursor++)
  1035.                     lin[cursor] = ' ';
  1036.             cursor = prev_cursor;
  1037.             break;
  1038.  
  1039.     /* Miscellanious control functions: */
  1040.         case TOGGLE_INSERT_MODE:
  1041.             Insert_mode = YES + NO - Insert_mode;
  1042.             if (Insert_mode == NO)
  1043.                 mesg ("", INS_MSG);
  1044.             else
  1045.                 mesg ("INSERT", INS_MSG);
  1046.             break;
  1047.  
  1048.         case SHIFT_CASE:
  1049.             Invert_case = YES + NO - Invert_case;
  1050.             if (Invert_case == NO)
  1051.                 mesg ("", CASE_MSG);
  1052.             else
  1053.                 mesg ("CASE", CASE_MSG);
  1054.             break;
  1055.  
  1056.         case KILL_ALL:
  1057.             nlpos = cursor = 0;
  1058.             break;
  1059.  
  1060.         case FIX_SCREEN:
  1061.             restore_screen ();
  1062.             break;
  1063.  
  1064.         default:
  1065.             status = ERR;
  1066.             mesg ("WHA?", CHAR_MSG);
  1067.             break;
  1068.         } /* end switch */
  1069.     } /* while (termchar == EOS) */
  1070.  
  1071.     lin[nlpos] = '\n';
  1072.     lin[nlpos + 1] = EOS;
  1073.  
  1074.     load ('|', Cmdrow, BARCOL);
  1075.     if (nlpos <= col1)
  1076.         loadstr ("", Cmdrow, POOPCOL, Ncols - 1);
  1077.     else
  1078.         loadstr (&lin[col1], Cmdrow, POOPCOL, Ncols - 1);
  1079.  
  1080.     if (cursor >= Warncol - 1)
  1081.         litnnum ("col ", cursor + 1, COL_MSG);
  1082.     else if (prev_cursor >= Warncol - 1)
  1083.         mesg ("", COL_MSG);
  1084.  
  1085.     *curpos = cursor;
  1086. }
  1087.  
  1088.  
  1089.  
  1090. /* cread --- read a character, handle interrupts and hangups */
  1091. /*              ALL keyboard input should pass through this routine */
  1092.  
  1093. int cread ()
  1094. {
  1095.     char c;
  1096.     int read ();
  1097.  
  1098.     tflush ();
  1099.     if (Peekc)
  1100.     {
  1101.         c = Peekc;
  1102.         Peekc = EOS;
  1103.     }
  1104.     else
  1105.     {
  1106. #ifdef BSD4_2
  1107.         Reading = YES;
  1108. #endif
  1109.         if (read (0, &c, 1) == -1)
  1110.             if (Hup_caught)
  1111.                 hangup ();
  1112.             else    /* must be a SIGINT at present */
  1113.             {
  1114.                 Int_caught = 0;
  1115.                 Errcode = ENOERR;
  1116.                 c = '\177';
  1117.             }
  1118. #ifdef BSD4_2
  1119.         Reading = NO;
  1120. #endif
  1121.     }
  1122.  
  1123.     return c;
  1124. }
  1125.  
  1126.  
  1127.  
  1128. /* scan_char --- scan current line for a character */
  1129.  
  1130. static int scan_char (chr, wrap, cursor, nlpos, lin, status)
  1131. char chr, *lin;
  1132. int wrap, cursor, nlpos, *status;
  1133. {
  1134.     register char c;
  1135.     register int inc, scan_pos;
  1136.     int cread ();
  1137.  
  1138.     c = cread ();
  1139.     if (Invert_case == YES && isalpha (c))
  1140.         c ^= 040;       /* toggle case */
  1141.     if (c == chr)
  1142.         c = Last_char_scanned;
  1143.     Last_char_scanned = c;
  1144.  
  1145.     if (chr == SCAN_LEFT || chr == G_SCAN_LEFT)
  1146.         inc = -1;
  1147.     else
  1148.         inc = 1;
  1149.  
  1150.     /* NOTE:  modify this code AT YOUR OWN RISK! */
  1151.     scan_pos = cursor;
  1152.     do
  1153.     {
  1154.         if (scan_pos < 0)
  1155.             if (wrap == NO)
  1156.                 break;
  1157.             else
  1158.                 scan_pos = nlpos;
  1159.         else if (scan_pos > nlpos)
  1160.             if (wrap == NO)
  1161.                 break;
  1162.             else
  1163.                 scan_pos = 0;
  1164.         else
  1165.             scan_pos += inc;
  1166.         if (-1 < scan_pos && scan_pos < nlpos && lin[scan_pos] == c)
  1167.             break;
  1168.     } while (scan_pos != cursor);
  1169.  
  1170.     if (scan_pos < 0 || scan_pos >= nlpos || lin[scan_pos] != c)
  1171.     {
  1172.         *status = ERR;
  1173.         mesg ("NOCHAR", CHAR_MSG);
  1174.     }
  1175.  
  1176.     return (scan_pos);
  1177. }
  1178.  
  1179.  
  1180.  
  1181. static int scan_tab (chr, cursor, status)
  1182. char chr;
  1183. int cursor, *status;
  1184. {
  1185.     register int inc, tab_pos;
  1186.  
  1187.     if (chr == TAB_LEFT)
  1188.     {
  1189.         inc = -1;
  1190.         tab_pos = cursor - 1;
  1191.     }
  1192.     else
  1193.     {
  1194.         inc = 1;
  1195.         tab_pos = cursor + 1;
  1196.     }
  1197.  
  1198.     for (; -1 < tab_pos && tab_pos < MAXLINE; tab_pos += inc)
  1199.         if (Tabstops[tab_pos] == YES)
  1200.             break;
  1201.  
  1202.     if (tab_pos < 0 || tab_pos >= MAXLINE - 1)
  1203.     {
  1204.         *status = ERR;
  1205.         mesg (smargin, CHAR_MSG);
  1206.     }
  1207.  
  1208.     return (tab_pos);
  1209. }
  1210.  
  1211.  
  1212.  
  1213. /* gobble --- delete characters starting at the current cursor position */
  1214.  
  1215. static gobble (len, cursor, status, nlpos, lin)
  1216. int len, cursor, *status, *nlpos;
  1217. char *lin;
  1218. {
  1219.     if (cursor + len > *nlpos)
  1220.     {
  1221.         *status = ERR;
  1222.         mesg (smargin, CHAR_MSG);
  1223.     }
  1224.     else if (len > 0)
  1225.     {
  1226.         strcpy (&lin[cursor], &lin[cursor + len]);
  1227.         *nlpos -= len;
  1228.     }
  1229. }
  1230.  
  1231.  
  1232.  
  1233. /* insert --- shift characters right starting at the current cursor position */
  1234.  
  1235. static insert (len, nlpos, status, cursor, lin)
  1236. register int len, *nlpos, cursor;
  1237. int *status;
  1238. register char *lin;
  1239. {
  1240.     register int fr, to;
  1241.  
  1242.     if (*nlpos + len >= MAXLINE - 1)
  1243.     {
  1244.         *status = ERR;
  1245.         mesg (smargin, CHAR_MSG);
  1246.     }
  1247.     else
  1248.     {
  1249.         for (fr = *nlpos, to = *nlpos + len; fr >= cursor; fr--, to--)
  1250.             lin[to] = lin[fr];
  1251.         *nlpos += len;
  1252.     }
  1253. }
  1254.  
  1255.  
  1256.  
  1257. /* set_cursor --- move the cursor, extend line if necessary */
  1258.  
  1259. static set_cursor (pos, status, cursor, nlpos, lin)
  1260. register int pos, *status, *cursor, *nlpos;
  1261. register char *lin;
  1262. {
  1263.     if (pos < 0 || pos >= MAXLINE - 1)
  1264.     {
  1265.         *status = ERR;
  1266.         mesg (smargin, CHAR_MSG);
  1267.     }
  1268.     else
  1269.     {
  1270.         *cursor = pos;
  1271.         for (; *nlpos < *cursor; (*nlpos)++)
  1272.             lin[*nlpos] = ' ';
  1273.     }
  1274. }
  1275.  
  1276.  
  1277. /* litnnum --- display literal and number in message area */
  1278.  
  1279. litnnum (lit, num, type)
  1280. register char *lit;
  1281. register int num, type;
  1282. {
  1283.     char msg[MAXLINE];
  1284.  
  1285.     sprintf (msg, "%s%d", lit, num);
  1286.     mesg (msg, type);
  1287. }
  1288.  
  1289.  
  1290.  
  1291. /* load --- load a character onto the screen at given coordinates */
  1292.  
  1293. load (chr, row, col)
  1294. register char chr;
  1295. register int row, col;
  1296. {
  1297.     register char ch;
  1298.  
  1299.     ch = (chr < ' ' || chr >= DEL) ? Unprintable : chr;
  1300.  
  1301.     if (row >= 0 && row < Nrows && col >= 0 && col < Ncols
  1302.         && Screen_image[row][col] != ch)
  1303.     {
  1304.         position_cursor (row, col);
  1305.         Screen_image[row][col] = ch;
  1306.         send (ch);
  1307.     }
  1308. }
  1309.  
  1310.  
  1311. /* loadstr --- load a string into a field of the screen */
  1312.  
  1313. loadstr (str, row, stcol, endcol)
  1314. register char *str;
  1315. int row, stcol, endcol;
  1316. {
  1317.     register char ch;
  1318.     register int p, c, limit;
  1319.  
  1320.     if (row >= 0 && row < Nrows && stcol >= 0)
  1321.     {
  1322.         c = stcol;
  1323.         for (p = 0; str[p] != EOS; p++)
  1324.         {
  1325.             if (c >= Ncols)
  1326.                 break;
  1327.             ch = str[p];
  1328.             if (ch < ' ' || ch >= DEL)
  1329.                 ch = Unprintable;
  1330.             if (Screen_image[row][c] != ch)
  1331.             {
  1332.                 Screen_image[row][c] = ch;
  1333.                 position_cursor (row, c);
  1334.                 send (ch);
  1335.             }
  1336.             c++;
  1337.         }
  1338.         if (endcol >= Ncols - 1 && c < Ncols - 1)
  1339.             clear_to_eol (row, c);
  1340.         else
  1341.         {
  1342.             limit = (endcol < Ncols - 1) ? endcol : Ncols - 1;
  1343.             for (; c <= limit; c++)
  1344.                 if (Screen_image[row][c] != ' ')
  1345.                 {
  1346.                     Screen_image[row][c] = ' ';
  1347.                     position_cursor (row, c);
  1348.                     send (' ');
  1349.                 }
  1350.         }
  1351.     }
  1352. }
  1353.  
  1354.  
  1355. /* mesg --- display a message in the status row */
  1356.  
  1357. mesg (s, t)
  1358. char *s;
  1359. register int t;
  1360. {
  1361.     register int col, need, c, first, last;
  1362.     int strlen ();
  1363.  
  1364.     for (first = 0; first < Ncols; first++)
  1365.         if (Msgalloc[first] == t)
  1366.             break;
  1367.     for (last = first; last < Ncols; last++)
  1368.     {
  1369.         if (Msgalloc[last] != t)
  1370.             break;
  1371.         Msgalloc[last] = NOMSG;
  1372.     }
  1373.     for (; first > 0 && Msgalloc[first - 1] == NOMSG; first--)
  1374.         ;
  1375.  
  1376.     need = strlen (s) + 2;  /* for two blanks */
  1377.  
  1378.     if (need > 2)           /* non-empty message */
  1379.     {
  1380.         if (need <= last - first)       /* fits in previous slot */
  1381.             col = first;        /* keep it there */
  1382.         else        /* needs a new slot */
  1383.             for (col = 0; col < Ncols - 1; col = c)
  1384.             {
  1385.                 while (col < Ncols - 1
  1386.                     && Msgalloc[col] != NOMSG)
  1387.                     col++;
  1388.                 for (c = col; Msgalloc[c] == NOMSG; c++)
  1389.                     if (c >= Ncols - 1)
  1390.                         break;
  1391.                 if (c - col >= need)
  1392.                     break;
  1393.             }
  1394.  
  1395.         if (col + need >= Ncols)        /* have to collect garbage */
  1396.         {
  1397.             col = 0;
  1398.             for (c = 0; c < Ncols; c++)
  1399.                 if (Msgalloc[c] != NOMSG)
  1400.                 {
  1401.                     load (Screen_image[Nrows - 1][c],
  1402.                         Nrows - 1, col);
  1403.                     Msgalloc[col] = Msgalloc[c];
  1404.                     col++;
  1405.                 }
  1406.             for (c = col; c < Ncols; c++)
  1407.                 Msgalloc[c] = NOMSG;
  1408.         }
  1409.  
  1410.         load (' ', Nrows - 1, col);
  1411.         loadstr (s, Nrows - 1, col + 1, 0);
  1412.         load (' ', Nrows - 1, col + need - 1);
  1413.         last = col + need - 1;
  1414.         if (last > Ncols - 1)
  1415.             last = Ncols - 1;
  1416.         for (c = col; c <= last; c++)
  1417.             Msgalloc[c] = t;
  1418.     }
  1419.  
  1420.     for (col = 0; col < Ncols; col++)
  1421.         if (Msgalloc[col] == NOMSG)
  1422.             load ('.', Nrows - 1, col);
  1423.     tflush ();
  1424. }
  1425.  
  1426. /* prompt --- load str into margin of command line */
  1427.  
  1428. prompt (str)
  1429. char *str;
  1430. {
  1431.     loadstr (str, Cmdrow, 0, BARCOL - 1);
  1432.     tflush ();
  1433. }
  1434.  
  1435.  
  1436.  
  1437. /* restore_screen --- screen has been garbaged; fix it */
  1438.  
  1439. restore_screen ()
  1440. {
  1441.     register int row, col;
  1442.     int intrpt ();
  1443.  
  1444.     clrscreen ();
  1445.     for (row = 0; row < Nrows && ! intrpt (); row++)
  1446.         for (col = 0; col < Ncols; col++)
  1447.             if (Screen_image[row][col] != ' ')
  1448.             {
  1449.                 position_cursor (row, col);
  1450.                 send (Screen_image[row][col]);
  1451.             }
  1452.  
  1453.     remark ("");    /* get rid of 'type control-q....' */
  1454. }
  1455.  
  1456. /* saynum --- display a number in the message area */
  1457.  
  1458. saynum (n)
  1459. int n;
  1460. {
  1461.     char s[MAXLINE];
  1462.  
  1463.     sprintf (s, "%d", n);
  1464.     remark (s);
  1465. }
  1466.  
  1467. /* updscreen --- update screen from edit buffer */
  1468.  
  1469. updscreen ()
  1470. {
  1471.     char abs_lineno[10], rel_lineno[10];
  1472.     register int line, row;
  1473.     register int i;
  1474.     int prevln ();
  1475.     register LINEDESC *k;
  1476.     LINEDESC *getind ();
  1477.  
  1478.     fixscreen ();
  1479.  
  1480.     line = Topln;
  1481.     k = getind (line);
  1482.  
  1483.     for (row = Toprow; row <= Botrow; row++)
  1484.     {
  1485.         if (line > Lastln || line < 1)
  1486.         {
  1487.             loadstr ("", row, 0, BARCOL - 1);
  1488.             load ('|', row, BARCOL);
  1489.             loadstr ("", row, BARCOL + 1, Ncols - 1);
  1490.         }
  1491.         else
  1492.         {
  1493.             if (line == Curln)
  1494.                 loadstr (".  ->", row, 0, NAMECOL - 1);
  1495.             else if (line == 1)
  1496.                 loadstr ("1", row, 0, NAMECOL - 1);
  1497.             else if (line == Lastln)
  1498.                 loadstr ("$", row, 0, NAMECOL - 1);
  1499.             else if (Absnos == NO && row <= 25)
  1500.             {
  1501.                 rel_lineno[0] = Rel_a + row;
  1502.                 rel_lineno[1] = EOS;
  1503.                 loadstr (rel_lineno, row, 0, NAMECOL - 1);
  1504.             }
  1505.             else
  1506.             {
  1507.                 sprintf (abs_lineno, "%d", line);
  1508.                 loadstr (abs_lineno, row, 0, NAMECOL - 1);
  1509.             }
  1510.  
  1511.             load ((char) k->Markname, row, NAMECOL);
  1512.             load ('|', row, BARCOL);
  1513.  
  1514.             if (line >= First_affected)
  1515.             {
  1516.                 gtxt (k);
  1517.                 if (Firstcol >= k->Lineleng)
  1518.                     loadstr ("", row, POOPCOL, Ncols - 1);
  1519.                 else
  1520.                     loadstr (&Txt[Firstcol], row, POOPCOL,
  1521.                         Ncols - 1);
  1522.             }
  1523.         }
  1524.  
  1525.         line++;
  1526.         k = NEXTLINE(k);
  1527.     }
  1528.  
  1529.     First_affected = Lastln;
  1530.  
  1531.     Sctop = Topln;
  1532.     Sclen = Botrow - Toprow + 1;
  1533.     for (i = 0; i < Sclen; i++)
  1534.         Scline[i] = Sctop + i <= Lastln ? i : -1;
  1535. }
  1536.  
  1537.  
  1538.  
  1539. /* warn_deleted --- indicate which rows on screen are no longer valid */
  1540.  
  1541. warn_deleted (from, to)
  1542. register int from, to;
  1543. {
  1544.     register int row;
  1545.  
  1546.     for (row = Toprow; row <= Botrow; row++)
  1547.         if (Topln + row - Toprow >= from
  1548.             && Topln + row - Toprow <= to)
  1549.             loadstr ("gone", row, 0, BARCOL - 1);
  1550. }
  1551.  
  1552.  
  1553. /* watch --- keep time displayed on screen for users without watches */
  1554.  
  1555. watch ()
  1556. {
  1557.     long clock;
  1558.     struct tm *now, *localtime ();
  1559.     char face[10];
  1560.  
  1561.     time (&clock);
  1562.     now = localtime (&clock);
  1563.     sprintf (face, "%02d:%02d", now->tm_hour, now->tm_min);
  1564.     mesg (face, TIME_MSG);
  1565. }
  1566.  
  1567. /* adjust_window --- position window to include lines 'from' through 'to' */
  1568.  
  1569. adjust_window (from, to)
  1570. register int from, to;
  1571. {
  1572.     register int i, l1, l2, hw;
  1573.     int hwinsdel();
  1574.  
  1575.     /* see if the whole range of lines is on the screen */
  1576.     if (from < Topln || to > Topln + (Botrow - Toprow))
  1577.     {
  1578.         /* find the first and last lines that are on the screen */
  1579.         for (i = 0; i < Sclen && Scline[i] == -1; i++)
  1580.             ;
  1581.         l1 = i < Sclen ? Scline[i] + Sctop : Lastln + 1;
  1582.         for (i = Sclen - 1; i >= 0 && Scline[i] == -1; i--)
  1583.             ;
  1584.         l2 = i >= 0 ? Scline[i] + Sctop : 0;
  1585.  
  1586.         /* see if we have hardware line insert/delete */
  1587.         hw = hwinsdel();
  1588.  
  1589.         /* now find the best place to move the screen */
  1590.         if (to - from > Botrow - Toprow)
  1591.             Topln = to - (Botrow - Toprow);     /* put last part on screen */
  1592.         else if (hw && from >= l1 && to <= l2)
  1593.             Topln = (l1 + l2 + Toprow - Botrow) / 2;/* center l1 through l2 */
  1594.         else if (hw && from < l1 && l1 - from < (Botrow - Toprow + 1) / 2)
  1595.             Topln = from;                       /* slide the screen down */
  1596.         else if (hw && to > l2 && to - l2 < (Botrow - Toprow + 1) / 2)
  1597.             Topln = to - (Botrow - Toprow);     /* slide the screen up */
  1598.         else
  1599.             Topln = (from + to + Toprow - Botrow) / 2; /* center the range */
  1600.         if (Topln + (Botrow - Toprow) > Lastln)
  1601.             Topln = Lastln - (Botrow - Toprow);
  1602.         if (Topln < 1)
  1603.             Topln = 1;
  1604.         if (First_affected > Topln)
  1605.             First_affected = Topln;
  1606.     }
  1607. }
  1608.  
  1609.  
  1610. /* svdel --- record the deletion of buffer lines for screen update */
  1611.  
  1612. svdel (ln, n)
  1613. register int ln, n;
  1614. {
  1615.     register int i, j, lb, ub;
  1616.  
  1617.     if (ln + n <= Sctop)
  1618.         Sctop -= n;
  1619.     else if (ln < Sctop)
  1620.     {
  1621.         ub = ln + n - Sctop;
  1622.         for (i = 0; i < Sclen; i++)
  1623.             if (Scline[i] == -1)
  1624.                 ;
  1625.             else if (Scline[i] < ub)
  1626.                 Scline[i] = -1;
  1627.             else
  1628.                 Scline[i] -= ub;
  1629.         Sctop = ln;
  1630.     }
  1631.     else
  1632.     {
  1633.         lb = ln - Sctop;
  1634.         ub = ln + n - Sctop;
  1635.         for (i = 0; i < Sclen; i++)
  1636.             if (Scline[i] == -1 || Scline[i] < lb)
  1637.                 ;
  1638.             else if (Scline[i] < ub)
  1639.                 Scline[i] = -1;
  1640.             else
  1641.                 Scline[i] -= n;
  1642.     }
  1643. }
  1644.  
  1645.  
  1646. /* svins --- record a buffer insertion for screen updating */
  1647.  
  1648. svins (ln, n)
  1649. register int ln, n;
  1650. {
  1651.     register int i, lb;
  1652.  
  1653.     if (ln < Sctop)
  1654.         Sctop += n;
  1655.     else
  1656.     {
  1657.         lb = ln - Sctop;
  1658.         for (i = 0; i < Sclen; i++)
  1659.             if (Scline[i] != -1 && Scline[i] > lb)
  1660.                 Scline[i] += n;
  1661.     }
  1662.  
  1663. }
  1664.  
  1665.  
  1666. /* fixscreen --- try to patch up the screen using insert/delete line */
  1667.  
  1668. fixscreen ()
  1669. {
  1670.     register int oi;    /* "old" screen index */
  1671.     register int ni;    /* "new" screen index */
  1672.     register int dc;    /* number of deletions in current block */
  1673.     register int ic;    /* number of insertions in current block */
  1674.     register int ul;    /* number of lines that must be rewritten if */
  1675.                 /* we don't update by insert/delete */
  1676.     int wline[MAXROWS];    /* new screen contents; Scline contains old */
  1677.     int p;
  1678.  
  1679.     /* if the screen width was changed, give up before it's too late */
  1680.     if (Botrow - Toprow + 1 != Sclen || ! hwinsdel())
  1681.         return;
  1682.  
  1683.     /* scale the offsets in Scline to the new Topln; set any that are */
  1684.     /* off the screen to -1 so we won't have to fool with them */
  1685.     for (oi = 0; oi < Sclen; oi++)
  1686.         if (Scline[oi] == -1 || Scline[oi] + Sctop < Topln
  1687.             || Scline[oi] + Sctop > Topln + (Botrow - Toprow))
  1688.             Scline[oi] = -1;
  1689.         else
  1690.             Scline[oi] += Sctop - Topln;
  1691.  
  1692.     /* fill in wline with only those numbers that are in Scline */
  1693.     for (oi = 0, ni = 0; ni < Sclen; ni++)
  1694.     {
  1695.         while (oi < Sclen && Scline[oi] == -1)
  1696.             oi++;
  1697.         if (oi < Sclen && Scline[oi] == ni)
  1698.         {
  1699.             wline[ni] = ni;
  1700.             oi++;
  1701.         }
  1702.         else
  1703.             wline[ni] = -1;
  1704.     }
  1705.  
  1706.     /* see if it's still advisable to fix the screen: if the number */
  1707.     /* of lines that must be rewritten is less than 2 + the number */
  1708.     /* of lines that must be inserted, don't bother (this is a dumb */
  1709.     /* but fairly effective heuristic) */
  1710.     ul = ni = 0;
  1711.     for (oi = 0; oi < Sclen; oi++)
  1712.     {
  1713.         if (Scline[oi] != wline[oi] || Scline[oi] == -1)
  1714.             ul++;
  1715.         if (wline[oi] == -1)
  1716.             ni++;
  1717.     }
  1718.     if (ul < ni + 2)
  1719.         return;
  1720.  
  1721.     /* Now scan the screens backwards and put out delete-lines */
  1722.     /* for all deletions and changes with more old lines than new */
  1723.     oi = ni = Sclen - 1;
  1724.     while (oi >= 0 || ni >= 0)
  1725.     {
  1726.         for (dc = 0; oi >= 0 && Scline[oi] == -1; dc++)
  1727.             oi--;
  1728.         for (ic = 0; ni >= 0 && wline[ni] == -1; ic++)
  1729.             ni--;
  1730.         if (dc > ic)
  1731.             dellines (oi + 1 + Toprow + ic, dc - ic);
  1732.         while (oi >= 0 && Scline[oi] != -1
  1733.             && ni >= 0 && wline[ni] == Scline[oi])
  1734.             oi--, ni--;
  1735.     }
  1736.  
  1737.     /* At last, scan the screens forward and put out insert-lines */
  1738.     /* for all insertions and changes with more new lines than old */
  1739.     oi = ni = 0;
  1740.     while (oi < Sclen || ni < Sclen)
  1741.     {
  1742.         p = ni;
  1743.         for (dc = 0; oi < Sclen && Scline[oi] == -1; dc++)
  1744.             oi++;
  1745.         for (ic = 0; ni < Sclen && wline[ni] == -1; ic++)
  1746.             ni++;
  1747.         if (ic > dc)
  1748.             inslines (p + Toprow + dc, ic - dc);
  1749.         while (oi < Sclen && Scline[oi] != -1
  1750.             && ni < Sclen && wline[ni] == Scline[oi])
  1751.             oi++, ni++;
  1752.     }
  1753.  
  1754. }
  1755. SHAR_EOF
  1756. fi # end of overwriting check
  1757. echo shar: extracting "'scriptse.1'" '(1863 characters)'
  1758. if test -f 'scriptse.1'
  1759. then
  1760.     echo shar: will not over-write existing file "'scriptse.1'"
  1761. else
  1762. cat << \SHAR_EOF > 'scriptse.1'
  1763. .\" 
  1764. .\" $Header: scriptse.1,v 1.2 86/07/11 15:17:32 osadr Exp $
  1765. .\" 
  1766. .\" $Log:    scriptse.1,v $
  1767. .\" Revision 1.2  86/07/11  15:17:32  osadr
  1768. .\" Removal of Georgia Tech specific items, and some cleaning up.
  1769. .\" 
  1770. .\" Revision 1.1  86/05/06  13:41:03  osadr
  1771. .\" Initial revision
  1772. .\" 
  1773. .\" 
  1774. .\" 
  1775. .TH SCRIPTSE 1 local
  1776. .SH NAME
  1777. scriptse \- make scripts for se
  1778. .SH SYNOPSIS
  1779. .B scriptse
  1780. [
  1781. .B \-d
  1782. ]
  1783. < script_file |
  1784. .B se
  1785. [ & ]
  1786. .SH DESCRIPTION
  1787. .I Scriptse
  1788. reads standard input, and writes standard output.
  1789. It is a simple filter which turns newlines ('\en') into carriage
  1790. returns ('\er') for
  1791. .IR se (1).
  1792. This allows
  1793. .I se
  1794. to be run from a prepared script.
  1795. .I Se
  1796. can then be fired off into the background, if you wish.
  1797. .PP
  1798. After each carriage return,
  1799. .I scriptse
  1800. adds an ASCII DEL character ('\e177').
  1801. This is so that command lines which fail will be erased,
  1802. and the next command can then be executed.
  1803. If it did not, command lines would get concatenated together, and they
  1804. would simply continue to fail.
  1805. Ultimately, the editor would run out of input buffer and start to
  1806. contiunuously ring the bell on the terminal.
  1807. With the DEL character, each command line is executed on its own.
  1808. .PP
  1809. .I Scriptse
  1810. takes one option, \-d.
  1811. If this option is used,
  1812. .I scriptse
  1813. will
  1814. .I not
  1815. add the ASCII DEL after each carriage return.
  1816. This is useful for program which want to turn newlines into carraige
  1817. returns.
  1818. .PP
  1819. If you do use a script, either sit back and watch it run, or redirect
  1820. the output into a file (or
  1821. .BR /dev/null ,
  1822. if you are confident).
  1823. .SH SEE ALSO
  1824. .IR se (1).
  1825. .SH CAVEATS
  1826. .PP
  1827. It is rather difficult to interrupt
  1828. .I se
  1829. when it is running, so editor scripts should write their
  1830. changed buffer to a new file, in case something goes wrong.
  1831. .SH BUGS
  1832. .PP
  1833. Does no checking for any of
  1834. .IR se 's
  1835. control characters.
  1836. If you put control characters into a script, you are taking your chances.
  1837. SHAR_EOF
  1838. fi # end of overwriting check
  1839. echo shar: extracting "'scriptse.c'" '(824 characters)'
  1840. if test -f 'scriptse.c'
  1841. then
  1842.     echo shar: will not over-write existing file "'scriptse.c'"
  1843. else
  1844. cat << \SHAR_EOF > 'scriptse.c'
  1845. #ifndef lint
  1846. static char RCSid[] = "$Header: scriptse.c,v 1.1 86/05/06 13:38:32 osadr Exp $";
  1847. #endif
  1848.  
  1849. /*
  1850.  * $Log:    scriptse.c,v $
  1851.  * Revision 1.1  86/05/06  13:38:32  osadr
  1852.  * Initial revision
  1853.  * 
  1854.  * 
  1855.  */
  1856.  
  1857. /*
  1858. ** scriptse.c
  1859. **
  1860. ** turn input into a form se
  1861. ** can use as a script.
  1862. **
  1863. ** This is very quick-and-dirty, not checking
  1864. ** for any of se's control characters.
  1865. */
  1866.  
  1867. #include <stdio.h>
  1868.  
  1869. main (argc, argv)
  1870. int argc;
  1871. char **argv;
  1872. {
  1873.     register int c;
  1874.     register int dflag = 0;
  1875.  
  1876.     if (argc > 1)
  1877.         if (strcmp (argv[1], "-d") == 0)
  1878.             dflag = 1;
  1879.         else
  1880.         {
  1881.             fprintf (stderr, "usage: %s [-d] < file > newfile\n",
  1882.                 argv[0]);
  1883.             exit (1);
  1884.         }
  1885.  
  1886.     while ((c = getchar()) != EOF)
  1887.     {
  1888.         if (c != '\n')        /* most frequent case */
  1889.             putchar (c);
  1890.         else
  1891.         {
  1892.             putchar ('\r');
  1893.             if (! dflag)
  1894.                 putchar ('\177');
  1895.         }
  1896.     }
  1897.     
  1898.     exit (0);
  1899. }
  1900. SHAR_EOF
  1901. fi # end of overwriting check
  1902. echo shar: extracting "'se.h'" '(7835 characters)'
  1903. if test -f 'se.h'
  1904. then
  1905.     echo shar: will not over-write existing file "'se.h'"
  1906. else
  1907. cat << \SHAR_EOF > 'se.h'
  1908. /*
  1909.  * $Header: se.h,v 1.3 86/07/11 15:09:54 osadr Exp $
  1910.  */
  1911.  
  1912. /*
  1913.  * $Log:    se.h,v $
  1914.  * Revision 1.3  86/07/11  15:09:54  osadr
  1915.  * Removed Many Georgia Tech specific things.
  1916.  * 
  1917.  * Revision 1.2  86/05/27  17:44:15  osadr
  1918.  * Removed flexnames dependancy on PREVLINE and PREVLINE2, changed to
  1919.  * PREVLN and PREVLN2.
  1920.  * 
  1921.  * Revision 1.1  86/05/06  13:36:23  osadr
  1922.  * Initial revision
  1923.  * 
  1924.  * 
  1925.  */
  1926.  
  1927. /* se.h    --- definitions    for the    screen editor */
  1928.  
  1929. #include <stdio.h>
  1930. #include <ctype.h>
  1931. #include <signal.h>
  1932.  
  1933. /* some standard definitions used throughout the screen editor */
  1934. #include "constdefs.h"
  1935. #include "ascii.h"    /* definitions of ascii characters */
  1936.  
  1937. /* new data types */
  1938. typedef    int filedes;        /* Unix    file descriptor    */
  1939.  
  1940. typedef    struct ldesc {        /* line    descriptor */
  1941. #ifdef OLD_SCRATCH
  1942.     struct    ldesc *Prevline; /* link to previous line */
  1943.     struct    ldesc *Nextline; /* link to next line */
  1944. #endif
  1945.     unsigned Seekaddr;    /* scratch file seek address / 8 */
  1946.     unsigned Lineleng : 16;    /* line length    including NL  EOS */
  1947.     unsigned Globmark : 1;    /* mark for global commands */
  1948.     unsigned Markname : 7;    /* mark name associated with line */
  1949. } LINEDESC;
  1950.  
  1951. /* Language extensions */
  1952. #define min(a,b)    ((a)<(b)?(a):(b))
  1953. #define max(a,b)    ((a)>(b)?(a):(b))
  1954. #define SKIPBL(l,i)    while (l[i] == ' ') (i)++
  1955.  
  1956. /* save a little procedure call overhead... */
  1957. #define remark(text)    mesg(text, REMARK_MSG)
  1958.  
  1959. /* Arbitrary definitions */
  1960. #define BACKWARD    -1
  1961. #define FORWARD        0
  1962. #define NOSTATUS    1
  1963. #define NOMORE        0
  1964. #define NEWLINE        '\n'
  1965. #define TAB        '\t'
  1966. #define RETERR    1
  1967. #define RETOK    0
  1968.  
  1969. /* Array dimensions and    other limit values */
  1970. #define MAXBUF        8192
  1971. #define MAXTOBUF    512
  1972. #define MAXCHARS    10
  1973. #define MAXROWS        200
  1974. #define MINROWS        16
  1975. #define MAXCOLS        200
  1976. #define MAXLINE        512
  1977. #define MAXPAT        512
  1978. #define GARB_FACTOR    2
  1979. #define GARB_THRESHOLD    1000
  1980. #define BUFENT        1
  1981. #define KEYSIZE        11
  1982.  
  1983. /* Message classes for status line at bottom of    screen */
  1984. #define NOMSG        0
  1985. #define REMARK_MSG    1
  1986. #define CHAR_MSG    2
  1987. #define CASE_MSG    3
  1988. #define INS_MSG        4
  1989. #define TIME_MSG    5
  1990. #define FILE_MSG    6
  1991. #define COL_MSG        7
  1992. #define LINE_MSG    8
  1993. #define COMPRESS_MSG    9
  1994. #define HELP_MSG    10
  1995. #define MODE_MSG    11
  1996. #define CRYPT_MSG    12
  1997.  
  1998. /* Characters typed by the user    */
  1999. #define ANYWAY        '!'
  2000. #define APPENDCOM    'a'
  2001. #define UCAPPENDCOM    'A'
  2002. #define BACKSCAN    '?'
  2003. #define BACKSEARCH    '<'
  2004. #define CHANGE        'c'
  2005. #define UCCHANGE    'C'
  2006. #define COPYCOM        't'
  2007. #define UCCOPYCOM    'T'
  2008. #define CURLINE        '.'
  2009. #define DEFAULTNAME    ' '
  2010. #define DELCOM        'd'
  2011. #define UCDELCOM    'D'
  2012. #define ENTER        'e'
  2013. #define UCENTER        'E'
  2014. #define ESCAPE        '\\'
  2015. #define EXCLUDE        'x'
  2016. #define UCEXCLUDE    'X'
  2017. #define GLOBAL        'g'
  2018. #define UCGLOBAL    'G'
  2019. #define GMARK        '\''
  2020. #define HELP        'h'
  2021. #define UCHELP        'H'
  2022. #define INSERT        'i'
  2023. #define UCINSERT    'I'
  2024. #define JOINCOM        'j'
  2025. #define UCJOINCOM    'J'
  2026. #define LASTLINE    '$'
  2027. #define LOCATECMD    'l'
  2028. #define UCLOCATECMD    'L'
  2029. #define MARKCOM        'k'
  2030. #define UCMARKCOM    'K'
  2031. #define MOVECOM        'm'
  2032. #define UCMOVECOM    'M'
  2033. #define NAMECOM        'n'
  2034. #define UCNAMECOM    'N'
  2035. #define NOTINCCL    '^'
  2036. #define OPTCOM        'o'
  2037. #define UCOPTCOM    'O'
  2038. #define PAGECOM        ':'
  2039. #define OVERLAYCOM    'v'
  2040. #define UCOVERLAYCOM    'V'
  2041. #define PREVLN        '^'
  2042. #define PREVLN2        '-'
  2043. #define PRINT        'p'
  2044. #define UCPRINT        'P'
  2045. #define PRINTCUR    '='
  2046. #define PRINTFIL    'f'
  2047. #define UCPRINTFIL    'F'
  2048. #define QUIT        'q'
  2049. #define UCQUIT        'Q'
  2050. #define READCOM        'r'
  2051. #define UCREADCOM    'R'
  2052. #define SCAN        '/'
  2053. #define SEARCH        '>'
  2054. #define SUBSTITUTE    's'
  2055. #define UCSUBSTITUTE    'S'
  2056. #define TLITCOM        'y'
  2057. #define UCTLITCOM    'Y'
  2058. #define TOPLINE        '#'
  2059. #define UNDOCOM        'u'
  2060. #define UCUNDOCOM    'U'
  2061. #define WRITECOM    'w'
  2062. #define UCWRITECOM    'W'
  2063. #define XMARK        '~'
  2064. #define MISCCOM        'z'
  2065. #define UCMISCCOM    'Z'
  2066. #define SHELLCOM    '!'
  2067.  
  2068. /* Error message numbers.  Arbitrary so    long as    they are different. */
  2069. #define EBACKWARD    1
  2070. #define ENOPAT        2
  2071. #define EBADPAT        3
  2072. #define EBADSTR        4
  2073. #define EBADSUB        5
  2074. #define ECANTREAD    6
  2075. #define EEGARB        7
  2076. #define EFILEN        8
  2077. #define EBADTABS    9
  2078. #define EINSIDEOUT    10
  2079. #define EKNOTFND    11
  2080. #define ELINE1        12
  2081. #define E2LONG        13
  2082. #define ENOERR        14
  2083. #define ENOLIMBO    15
  2084. #define EODLSSGTR    16
  2085. #define EORANGE        17
  2086. #define EOWHAT        18
  2087. #define EPNOTFND    19
  2088. #define ESTUPID        20
  2089. #define EWHATZAT    21
  2090. #define EBREAK        22
  2091. #define ELINE2        23
  2092. #define ECANTWRITE    24
  2093. #define ECANTINJECT    25
  2094. #define ENOMATCH    26
  2095. #define ENOFN        27
  2096. #define EBADLIST    28
  2097. #define ENOLIST        29
  2098. #define ENONSENSE    30
  2099. #define ENOHELP        31
  2100. #define EBADLNR        32
  2101. #define EFEXISTS    33
  2102. #define EBADCOL        34
  2103. #define ENOLANG        35
  2104. #define ETRUNC        36
  2105. #define ENOSHELL    37
  2106. #define ECANTFORK    38
  2107. #define EHANGUP        39
  2108. #define ENOSUB        40
  2109. #define ENOCMD        41
  2110.  
  2111. #ifdef HARD_TERMS
  2112. /* Terminal types */
  2113. #define NOTERM        0    /* type    not known yet */
  2114. #define ADDS980        1    /* ADDS    Consul 980 */
  2115. #define ADDS100        2    /* ADDS    Regent 100, 20,    40, etc    */
  2116. #define FOX        3    /* Perkin-Elmer    1100 */
  2117. #define TVT        4    /* Allen's SWTPC T. V. Typewriter II */
  2118. #define GT40        5    /* DEC GT40 with Waugh terminal    program    */
  2119. #define BEE150        6    /* Beehive 150 */
  2120. #define BEE200        7    /* Beehive 200 */
  2121. #define SBEE        8    /* Beehive Super-Bee */
  2122. #define SOL        9    /* Sol emulating Beehive 200 */
  2123. #define HAZ1510        10    /* Hazeltine 1500 series */
  2124. #define CG        11    /* Chromatics CG */
  2125. #define ISC8001        12    /* ISC 8001 color terminal */
  2126. #define ADM3A        13    /* Lear-Siegler    ADM 3A */
  2127. #define IBM        14    /* IBM 3101 */
  2128. #define ANP        15    /* Allen & Paul    model 1    */
  2129. #define NETRON        16    /* Netronics */
  2130. #define H19        17    /* Heath H19/Zenith Z19    */
  2131. #define TRS80        18    /* Radio Shaft TRS80 */
  2132. #define HP21        19    /* Hewlett-Packard 2621A/P */
  2133. #define ADM31        20    /* Lear-Siegler    ADM 31 */
  2134. #define VI200        21    /* VIsual 200 terminal */
  2135. #define VC4404        22    /* Volker-Craig    4404 */
  2136. #define ESPRIT        23    /* Hazeltine Esprit (Hazeltine mode) */
  2137. #define TS1        24    /* Falco TS-1 */
  2138. #define TVI950        25    /* Televideo 950 */
  2139. #define VI50        26    /* Visual 50 */
  2140. #define VI300        27    /* Visual 300    */
  2141. #endif
  2142.  
  2143. /* Screen design positions */
  2144. #define NAMECOL        5    /* column to put mark name in */
  2145. #define BARCOL        6    /* column for "|" divider */
  2146. #define POOPCOL        7    /* column for text to start in */
  2147.  
  2148. /* Control characters */
  2149.  
  2150. /* Leftward cursor motion */
  2151. #define CURSOR_LEFT        CTRL_H    /* left    one column */
  2152. #define TAB_LEFT        CTRL_E    /* left    one tab    stop */
  2153. #define SKIP_LEFT        CTRL_W    /* go to column    1 */
  2154. #define SCAN_LEFT        CTRL_L    /* scan    left for a char    */
  2155. #define G_LEFT            CTRL_U    /* erase char to left */
  2156. #define G_TAB_LEFT        FS    /* erase to prev tab stop */
  2157. #define KILL_LEFT        CTRL_Y    /* erase to column 1 */
  2158. #define G_SCAN_LEFT        CTRL_N    /* scan    left and erase */
  2159.  
  2160. /* Rightward cursor motion */
  2161. #define CURSOR_RIGHT        CTRL_G    /* right one column */
  2162. #define TAB_RIGHT        CTRL_I    /* right one tab stop */
  2163. #define SKIP_RIGHT        CTRL_O    /* go to end of    line */
  2164. #define SCAN_RIGHT        CTRL_J    /* scan    right for char */
  2165. #define G_RIGHT            CTRL_R    /* erase over cursor */
  2166. #define G_TAB_RIGHT        RS    /* erase to next tab */
  2167. #define KILL_RIGHT        CTRL_T    /* erase to end    of line    */
  2168. #define G_SCAN_RIGHT        CTRL_B    /* scan    right and erase    */
  2169.  
  2170. /* Line    termination */
  2171. #define T_SKIP_RIGHT        CTRL_V    /* skip    to end and terminate */
  2172. #define T_KILL_RIGHT        CR    /* KILL_RIGHT,    SKIP_RIGHT_AND_TERM */
  2173. #define FUNNY            CTRL_F    /* take    funny return */
  2174. #define CURSOR_UP        CTRL_D    /* move    up one line */
  2175. #define CURSOR_DOWN        CTRL_K    /* move    down one line */
  2176. #define CURSOR_SAME        CTRL_J    /* leave cursor    on same    line */
  2177.  
  2178. /* Insertion */
  2179. #define INSERT_BLANK        CTRL_C    /* insert one blank */
  2180. #define INSERT_TAB        CTRL_X    /* insert blanks to next tab */
  2181. #define INSERT_NEWLINE        US    /* insert a newline */
  2182.  
  2183. /* Miscellany */
  2184. #define TOGGLE_INSERT_MODE    CTRL_A    /* toggle insert mode flag */
  2185. #define SHIFT_CASE        CTRL_Z    /* toggle case mapping flag */
  2186. #define KILL_ALL        DEL    /* erase entire    line */
  2187. #define FIX_SCREEN        GS    /* clear and restore screen */
  2188.  
  2189. /* Function for moving around the buffer, either style line handling: */
  2190. #ifdef OLD_SCRATCH
  2191. #define NEXTLINE(k)    ((k) -> Nextline)
  2192. #else
  2193. #define NEXTLINE(k)    (((k) < &Buf[Lastln]) ? (k) + 1 : Line0)
  2194. #endif
  2195. SHAR_EOF
  2196. fi # end of overwriting check
  2197. echo shar: extracting "'where'" '(1190 characters)'
  2198. if test -f 'where'
  2199. then
  2200.     echo shar: will not over-write existing file "'where'"
  2201. else
  2202. cat << \SHAR_EOF > 'where'
  2203. #! /bin/sh
  2204. # $Header: where,v 1.2 86/07/11 15:14:10 osadr Exp $
  2205. # $Log:    where,v $
  2206. # Revision 1.2  86/07/11  15:14:10  osadr
  2207. # Removed Georgia Tech specific items.
  2208. # Revision 1.1  86/05/06  13:34:27  osadr
  2209. # Initial revision
  2210.  
  2211. # where --- shell file to determine what kind of environment we are in
  2212.  
  2213. if test -r /bin/universe    # on a pyramid
  2214. then
  2215.     OPATH=$PATH
  2216.     PATH=/bin
  2217.     case `universe` in    # universe is dumb, looking only at argv[0]
  2218.     att)    echo "-DUSG -UBSD -UBSD4_2"
  2219.         if grep LOBLK /usr/include/sys/termio.h > /dev/null
  2220.         then
  2221.             echo -DS5R2
  2222.         else
  2223.             echo -US5R2
  2224.         fi
  2225.         ;;
  2226.  
  2227.     ucb)    echo "-UUSG -DBSD -DBSD4_2 -US5R2"
  2228.         ;;
  2229.  
  2230.     *)    echo unknown operating system! 1>&2
  2231.         echo "-UUSG -UBSD -UBSD4_2"    # undefine them all
  2232.         echo "-US5R2"
  2233.         ;;
  2234.     esac
  2235.     PATH=$OPATH
  2236. else        # on something that is not a pyramid
  2237.     if grep SIGTSTP /usr/include/signal.h > /dev/null
  2238.     then        # berkeley unix
  2239.         if test -r /usr/include/whoami.h    # 4.1
  2240.         then
  2241.             echo "-UUSG -DBSD -UBSD4_2"
  2242.         else                    # 4.2
  2243.             echo "-UUSG -DBSD -DBSD4_2"
  2244.         fi
  2245.         echo -US5R2
  2246.     else            # ATT unix
  2247.         echo "-DUSG -UBSD -UBSD4_2"
  2248.         if grep LOBLK /usr/include/sys/termio.h > /dev/null
  2249.         then
  2250.             echo -DS5R2
  2251.         else
  2252.             echo -US5R2
  2253.         fi
  2254.     fi
  2255. fi
  2256. SHAR_EOF
  2257. chmod +x 'where'
  2258. fi # end of overwriting check
  2259. #    End of shell archive
  2260. exit 0
  2261.  
  2262.